import Express from 'express';

import { ObjectWithGivenValues } from '@donnu-prod-practice/types';

export type CustomErrorType = (
  res: Express.Response,
  status: number,
  message: string
) => Express.Response<{ status: number; message: string }>;

/* -------------------------------------------------------------------------- */

export interface ParamsType {
  readonly [key: string]: string | number;
}

/* -------------------------------------------------------------------------- */

export interface QueryType {
  readonly [key: string]: string | number | boolean;
}

/* -------------------------------------------------------------------------- */

export interface BodyType {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  readonly [key: string]: any;
}

/* -------------------------------------------------------------------------- */

export type ControllerType<
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  P extends { [key: string]: any } = ParamsType,
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  Q extends { [key: string]: any } = QueryType,
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  B extends { [key: string]: any } = BodyType,
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  R = any
> = (
  request: Express.Request<
    ObjectWithGivenValues<P, ParamsType[0] | undefined>,
    // P,
    R,
    ObjectWithGivenValues<B, unknown>,
    ObjectWithGivenValues<Q, QueryType[0] | undefined>
    // ExpressCore.Query
  >,
  response: Express.Response<R>,
  next: Express.NextFunction
) => Promise<Express.Response<R> | ReturnType<Express.NextFunction> | ReturnType<CustomErrorType>>;

/* -------------------------------------------------------------------------- */

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type AnyRequestType = Express.Request<any, any, any, any>;
